/**
 * 矢量图层类
 * 支持点、线、面等矢量要素的展示和编辑
 */

import { Map as OlMap } from 'ol';
import { Vector as OlVectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Feature } from 'ol';
import { Geometry, Point, LineString, Polygon } from 'ol/geom';
import { BaseLayer } from './BaseLayer';
import { VectorLayerOptions, FeatureData, Coordinate, DataAdapterOptions, BatchImportOptions, LoadProgress } from '../types';
import { DataUtil } from '../utils/data';
import { StyleUtil } from '../utils/style';
import { Style } from 'ol/style';

/**
 * 矢量图层类
 */
export class VectorLayer extends BaseLayer {
  /** 图层配置 */
  protected options: VectorLayerOptions;
  /** 矢量数据源 */
  private source: VectorSource<Feature<Geometry>> | null = null;

  /**
   * 构造函数
   * @param options 图层配置
   */
  constructor(options: VectorLayerOptions = {}) {
    super(options);
    this.options = options;
  }

  /**
   * 创建图层
   */
  protected createLayer(): void {
    this.source = new VectorSource<Feature<Geometry>>();

    this.layer = new OlVectorLayer({
      source: this.source,
      style: (feature: any) => this.getStyle(feature as Feature<Geometry>)
    });

    // 监听点击事件
    if (this.map) {
      this.map.on('click', (event) => {
        this.handleClick(event);
      });
    }

    // 监听数据变化，更新图层样式等
    this.watchData(({ key, value }) => {
      this.handleDataChange(key, value);
    });
  }

  /**
   * 处理数据变化
   * @param key 数据标识键
   * @param value 数据值
   */
  private handleDataChange(key: string, value: any): void {
    // 根据业务数据更新图层要素
    // 例如根据销售额更新点的样式
    if (this.source) {
      this.source.getFeatures().forEach(feature => {
        const featureId = feature.getId();
        if (featureId && value[featureId]) {
          // 更新要素属性
          feature.setProperties(value[featureId], false);
          // 可以根据需要触发重绘
        }
      });
    }
  }

  /**
   * 使用数据适配器加载数据
   * @param data 原始数据
   * @param adapterOptions 数据适配器配置
   * @param importOptions 批量导入配置
   * @param onProgress 进度回调
   * @returns Promise<void>
   */
  async loadDataWithAdapter(
    data: any[],
    adapterOptions: DataAdapterOptions,
    importOptions: BatchImportOptions = {},
    onProgress?: (progress: LoadProgress) => void
  ): Promise<void> {
    // 初始化数据适配器
    this.initDataAdapter(adapterOptions);
    
    // 批量导入数据
    const features = await this.batchImport(data, importOptions, onProgress);
    
    // 添加到图层
    if (this.source) {
      this.source.clear();
      this.source.addFeatures(features);
    }
  }

  /**
   * 获取要素样式
   * @param feature 要素
   * @returns 样式
   */
  private getStyle(feature: Feature<Geometry>): Style | Style[] {
    // 使用自定义样式函数
    if (this.options.styleFunction) {
      return this.options.styleFunction(feature);
    }

    const geometry = feature.getGeometry();
    if (!geometry) {
      return new Style();
    }

    // 根据几何类型返回默认样式
    if (geometry instanceof Point) {
      return this.options.defaultPointStyle || StyleUtil.createCircleStyle();
    } else if (geometry instanceof LineString) {
      return this.options.defaultLineStyle || StyleUtil.createLineStyle();
    } else if (geometry instanceof Polygon) {
      return this.options.defaultPolygonStyle || StyleUtil.createPolygonStyle();
    }

    return new Style();
  }

  /**
   * 处理点击事件
   * @param event 点击事件
   */
  private handleClick(event: any): void {
    if (!this.map || !this.layer) return;

    const feature = this.map.forEachFeatureAtPixel(
      event.pixel,
      (feature) => feature,
      {
        layerFilter: (layer) => layer === this.layer
      }
    );

    if (feature) {
      const geometry = feature.getGeometry();
      if (geometry) {
        let coordinate: Coordinate;
        if (geometry instanceof Point) {
          coordinate = DataUtil.fromOlCoordinate(geometry.getCoordinates() as [number, number]);
        } else {
          // 对于线和面，返回中心点
          const extent = geometry.getExtent();
          coordinate = DataUtil.fromOlCoordinate([
            (extent[0] + extent[2]) / 2,
            (extent[1] + extent[3]) / 2
          ]);
        }

        this.emit('featureclick', {
          feature,
          coordinate,
          properties: feature.getProperties()
        });
      }
    }
  }

  /**
   * 添加要素
   * @param data 要素数据
   */
  addFeature(data: FeatureData): void {
    if (!this.source) {
      throw new Error('Layer not initialized');
    }

    const feature = DataUtil.createFeatureFromData(data);
    if (data.id !== undefined) {
      feature.setId(data.id);
    }
    this.source.addFeature(feature);
    this.emit('featureadd', feature);
  }

  /**
   * 批量添加要素
   * @param dataList 要素数据数组
   */
  addFeatures(dataList: FeatureData[]): void {
    if (!this.source) {
      throw new Error('Layer not initialized');
    }

    const features = dataList.map(data => {
      const feature = DataUtil.createFeatureFromData(data);
      if (data.id !== undefined) {
        feature.setId(data.id);
      }
      return feature;
    });

    this.source.addFeatures(features);
    this.emit('featuresadd', features);
  }

  /**
   * 移除要素
   * @param featureId 要素ID
   */
  removeFeature(featureId: string | number): void {
    if (!this.source) return;

    const feature = this.source.getFeatureById(featureId);
    if (feature && feature instanceof Feature) {
      this.source.removeFeature(feature);
      this.emit('featureremove', feature);
    }
  }

  /**
   * 清空所有要素
   */
  clearFeatures(): void {
    if (this.source) {
      this.source.clear();
      this.emit('featuresclear');
    }
  }

  /**
   * 更新数据
   * @param dataList 要素数据数组
   */
  updateData(dataList: FeatureData[]): void {
    this.clearFeatures();
    this.addFeatures(dataList);
  }

  /**
   * 设置样式函数
   * @param styleFunction 样式函数
   */
  setStyleFunction(styleFunction: (feature: Feature<Geometry>) => Style | Style[]): void {
    this.options.styleFunction = styleFunction;
    if (this.layer) {
      (this.layer as OlVectorLayer<VectorSource<Feature<Geometry>>>).setStyle((feature: any) => this.getStyle(feature as Feature<Geometry>));
    }
  }

  /**
   * 获取所有要素
   * @returns 要素数组
   */
  getFeatures(): Feature<Geometry>[] {
    return this.source?.getFeatures() || [];
  }

  /**
   * 根据ID获取要素
   * @param featureId 要素ID
   * @returns 要素
   */
  getFeatureById(featureId: string | number): Feature<Geometry> | null {
    const feature = this.source?.getFeatureById(featureId);
    return feature instanceof Feature ? feature : null;
  }

  /**
   * 从GeoJSON加载数据
   * @param geoJson GeoJSON对象
   */
  fromGeoJSON(geoJson: any): void {
    const features = DataUtil.fromGeoJSON(geoJson);
    if (this.source) {
      this.source.addFeatures(features);
      this.emit('featuresadd', features);
    }
  }

  /**
   * 导出为GeoJSON
   * @returns GeoJSON对象
   */
  toGeoJSON(): any {
    if (!this.source) {
      return { type: 'FeatureCollection', features: [] };
    }
    return DataUtil.toGeoJSON(this.source.getFeatures());
  }
}

